package com.cxm.helper.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cxm.helper.exception.BusinessException;
import com.cxm.helper.pojo.Config;
import com.cxm.helper.pojo.User;
import com.cxm.helper.pojo.dto.ConfigSaveDTO;
import com.cxm.helper.pojo.vo.ConfigVO;
import com.cxm.helper.service.ConfigService;
import com.cxm.helper.mapper.ConfigMapper;
import com.cxm.helper.service.UserService;
import com.cxm.helper.util.BeanUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author chenximeng
 * @description 针对表【config】的数据库操作Service实现
 * @createDate 2022-11-20 09:25:37
 */
@Service
public class ConfigServiceImpl extends ServiceImpl<ConfigMapper, Config>
        implements ConfigService {

    @Autowired
    ConfigMapper configMapper;
    @Autowired
    UserService userService;

    private List<String> getRepeatConfigName(List<String> configName) {
        List<String> repeatConfigName = CollUtil.newArrayList();

        List<String> oldConfigNames = list().stream().map(Config::getConfigName).collect(Collectors.toList());
        for (String str : configName) {
            if (oldConfigNames.contains(str)) {
                repeatConfigName.add(str);
            }
        }
        return repeatConfigName;
    }

    @Override
    public List<String> add(ConfigSaveDTO configDto) {
        List<String> configName = configDto.getChildren().stream().map(ConfigSaveDTO::getConfigName).collect(Collectors.toList());
        configName.add(configDto.getConfigName());
        List<String> repeatConfigName = getRepeatConfigName(configName);
        if (CollUtil.isNotEmpty(repeatConfigName)) {
            return repeatConfigName;
        }
        Config config = new Config();
        BeanUtils.copyProperties(configDto, config);
        configMapper.insert(config);
        if (CollUtil.isEmpty(configDto.getChildren())) {
            return CollUtil.newArrayList();
        }
        List<Config> list = new ArrayList<>();
        for (ConfigSaveDTO child : configDto.getChildren()) {
            Config configChild = new Config();
            configChild.setParentId(config.getId());
            configChild.setCreateUser(config.getCreateUser());
            BeanUtils.copyProperties(child, configChild);
            list.add(configChild);
        }
        saveBatch(list);
        return CollUtil.newArrayList();
    }

    @Override
    public List<ConfigVO> listConfigAndChildren() {
        List<Config> list = list();
        if (CollUtil.isEmpty(list)) {
            return CollUtil.newArrayList();
        }
        List<ConfigVO> configVOList = BeanUtil.copyList(list, ConfigVO.class);
        List<Long> createUserList = configVOList.stream().map(configVO -> configVO.getCreateUser()).collect(Collectors.toList());
        List<User> users = userService.listByIds(createUserList);
        Map<Long, String> userNicknameMap = users.stream().collect(Collectors.toMap(User::getId, User::getNickname));
        configVOList = configVOList.stream().map(config -> {
            config.setCreateUserNickname(userNicknameMap.get(config.getCreateUser()));
            return config;
        }).collect(Collectors.toList());
        List<ConfigVO> parentList = configVOList.stream().filter(config -> config.getParentId() == null)
                .collect(Collectors.toList());

        Map<Long, List<ConfigVO>> parentIdMap = configVOList.stream().filter(config -> config.getParentId() != null)
                .collect(Collectors.groupingBy(ConfigVO::getParentId, Collectors.toList()));

        for (ConfigVO parent : parentList) {
            parent.setChildren(parentIdMap.get(parent.getId()));
        }
        return parentList;
    }

    @Override
    public List<String> update(ConfigSaveDTO dto) {
        List<Config> oldChildren = list(new QueryWrapper<Config>().eq("parent_id", dto.getId()));
        Config config = new Config();
        BeanUtils.copyProperties(dto, config);
        List<Config> configs = BeanUtil.copyList(dto.getChildren(), Config.class);
        updateById(config);
        if (CollUtil.isEmpty(oldChildren)) {
            saveBatch(configs);
            return CollUtil.newArrayList();
        }
        Map<Long, Config> map = oldChildren.stream().collect(Collectors.toMap(Config::getId, item -> item));
        List<Long> oldIds = oldChildren.stream().map(Config::getId).collect(Collectors.toList());
        List<Long> newIds = configs.stream().map(Config::getId).collect(Collectors.toList());
        List<Config> addList = CollUtil.newArrayList();
        List<Config> updateList = CollUtil.newArrayList(config);
        List<Long> delIds = oldIds.stream().filter(item -> !newIds.contains(item)).collect(Collectors.toList());
        for (Config newConfig : configs) {
            newConfig.setParentId(config.getId());
            Config oldConfig = map.get(newConfig.getId());
            if (oldConfig == null) {
                addList.add(newConfig);
                continue;
            }
            updateList.add(newConfig);
        }
        List<String> repeatConfigName = getRepeatConfigName(addList.stream().map(Config::getConfigName).collect(Collectors.toList()));
        if (CollUtil.isNotEmpty(repeatConfigName)) {
            return repeatConfigName;
        }
        if (CollUtil.isNotEmpty(addList)) {
            saveBatch(addList);
        }
        if (CollUtil.isNotEmpty(updateList)) {
            updateBatchById(updateList);
        }
        if (CollUtil.isNotEmpty(delIds)) {
            removeByIds(delIds);
        }
        return repeatConfigName;
    }

    @Override
    public void deepDeleteByParentId(Long id) {
        configMapper.delete((new QueryWrapper<Config>()).eq("id", id).or().eq("parent_id", id));
    }

    @Override
    public void deleteChildrenByParentId(Long id) {
        configMapper.delete((new QueryWrapper<Config>()).eq("parent_id", id));
    }

    @Override
    public Config getByConfigName(String configName) {
        return configMapper.selectOne(new QueryWrapper<Config>().eq("config_name", configName));
    }

    @Override
    public List<Config> getByConfigNames(List<String> configName) {
        return list(new QueryWrapper<Config>().in("config_name", configName));
    }

    @Override
    public List<Config> listChildByParentConfigName(String configName) {
        Config config = getByConfigName(configName);
        return listChildByParentId(config.getId());
    }

    @Override
    public List<Config> listChildByParentId(Long parentId) {
        return configMapper.selectList(new QueryWrapper<Config>().eq("parent_id", parentId));
    }


}




